﻿

#region Usings
using System;
using System.Security.Cryptography;
using System.Text;
using Jenvin.Library.Utils.Encryption;

#endregion

namespace Jenvin.Library.Utils.Encryption
{
    /// <summary>
    /// 非对称加密Rsa
    /// </summary>
    public class RSAEncryption : IAysmEncryption
    {
        private static RSACryptoServiceProvider RSA = null;

        /// <summary>
        /// 加密Key
        /// </summary>
        public string Key
        {
            get;
            set;
        }

        public string IV
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// Rsa 加密
        /// </summary>
        /// <param name="Input">input 数据应该小于128 个字节。超过128 个字节的数据。不会被加密 </param>
        /// <param name="Key">加密Key使用CreateKey创建</param>
        /// <returns>密文 64Bit </returns>
        public string Encrypt(string input)
        {
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(Key);
            Encoding Encoding = System.Text.Encoding.Default;
            byte[] InputArray = Encoding.GetBytes(input);
            byte[] EncryptedBytes = RSA.Encrypt(InputArray, true);
            RSA.Clear();
            return Convert.ToBase64String(EncryptedBytes);
        }

        /// <summary>
        /// Rsa 解密
        /// </summary>
        /// <param name="Input">Input string (should be small as anything over 128 bytes can not be decrypted)</param>
        /// <param name="Key">解密Key使用CreateKey创建</param>
        /// <returns>明文</returns>
        public string Decrypt(string input)
        {
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(Key);
            byte[] InputArray = Convert.FromBase64String(input);
            byte[] EncryptedBytes = RSA.Decrypt(InputArray, true);
            RSA.Clear();
            return System.Text.Encoding.Default.GetString(EncryptedBytes);
        }

        /// <summary>
        ///创建一个新密钥对 
        /// </summary>
        /// <param name="PrivatePublic">ture 表示包含私钥。false 表示不包含</param>
        /// <returns> 包含Key 的xml</returns>
        public string CreateKey(bool privatePublic)
        {
            if (RSA == null)
            {
                RSA = new RSACryptoServiceProvider();
            }
            return RSA.ToXmlString(privatePublic);

        }

        /// <summary>
        /// 生成摘要。并给摘要签名
        /// </summary>
        /// <param name="input">数据</param>
        /// <param name="hash">数据的摘要</param>
        /// <returns>生成后摘要并签名的数据 64 bit</returns>
        public string SignHash(string input, out string hash)
        {
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(Key);
            Encoding Encoding = System.Text.Encoding.Default;
            byte[] InputArray = Encoding.GetBytes(input);
            System.Security.Cryptography.SHA1 SHA = System.Security.Cryptography.SHA1.Create();
            byte[] HashBytes = SHA.ComputeHash(InputArray);
            byte[] SignedHash = RSA.SignHash(HashBytes, CryptoConfig.MapNameToOID("SHA1"));
            SHA.Clear();
            RSA.Clear();
            hash = Convert.ToBase64String(HashBytes);
            return Convert.ToBase64String(SignedHash);
        }

        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="hash">原始摘要 64bit String</param>
        /// <param name="signedHash">签名后的摘要 64bit String</param>
        /// <returns></returns>
        public bool VerifyHash(string hash, string signedHash)
        {
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.FromXmlString(Key);
            byte[] InputArray = Convert.FromBase64String(signedHash);
            byte[] HashArray = Convert.FromBase64String(hash);
            bool Result = RSA.VerifyHash(HashArray, CryptoConfig.MapNameToOID("SHA1"), InputArray);
            RSA.Clear();
            return Result;
        }

        #region ISymEncryption 成员


        public void Encrypt(System.IO.Stream inputStream, System.IO.Stream outputStream)
        {
            throw new NotImplementedException();
        }

        public void Decrypt(System.IO.Stream inputStream, System.IO.Stream outputStream)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}